<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>SQL Server 存储过程示例</title>
    <style>
        body {
            margin: 0;
            padding: 20px;
            font-family: Arial, sans-serif;
            background: #f5f5f5;
            line-height: 1.6;
        }

        .container {
            max-width: 1200px;
            margin: 0 auto;
            padding: 20px;
            background: #fff;
            border-radius: 8px;
            box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
        }

        h1, h2, h3 {
            color: #303133;
            margin-top: 30px;
        }

        .code-block {
            background: #f8f9fa;
            padding: 15px;
            border-radius: 4px;
            border: 1px solid #e9ecef;
            overflow-x: auto;
            margin: 15px 0;
            font-family: Consolas, monospace;
            font-size: 14px;
            line-height: 1.5;
        }

        .note {
            background: #ecf8ff;
            padding: 15px;
            border-radius: 4px;
            border-left: 4px solid #409EFF;
            margin: 15px 0;
        }

        .warning {
            background: #fff9e6;
            padding: 15px;
            border-radius: 4px;
            border-left: 4px solid #e6a23c;
            margin: 15px 0;
        }

        table {
            width: 100%;
            border-collapse: collapse;
            margin: 15px 0;
        }

        th, td {
            border: 1px solid #EBEEF5;
            padding: 12px 8px;
            text-align: left;
        }

        th {
            background-color: #F5F7FA;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>SQL Server 存储过程 - 数据库表同步示例</h1>
        
        <div class="note">
            本文将介绍如何使用 SQL Server 存储过程实现两个数据库之间的表数据同步。
        </div>

        <h2>1. 创建示例表结构</h2>
        <p>首先在源数据库和目标数据库中创建相同的用户表结构：</p>
        
        <div class="code-block">
<pre>
-- 在源数据库和目标数据库中都需要执行以下脚本
CREATE TABLE [dbo].[Users](
    [UserID] INT IDENTITY(1,1) PRIMARY KEY,
    [Username] NVARCHAR(50) NOT NULL,
    [Email] NVARCHAR(100) NULL,
    [Mobile] VARCHAR(20) NULL,
    [Status] TINYINT NOT NULL DEFAULT(1),
    [CreatedTime] DATETIME NOT NULL DEFAULT(GETDATE()),
    [UpdatedTime] DATETIME NULL,
    CONSTRAINT [UQ_Users_Username] UNIQUE([Username])
);

-- 在源数据库中插入一些测试数据
INSERT INTO [dbo].[Users] ([Username], [Email], [Mobile], [Status])
VALUES 
    ('admin', 'admin@example.com', '13800138000', 1),
    ('user1', 'user1@example.com', '13800138001', 1),
    ('user2', 'user2@example.com', '13800138002', 1);

-- 在目标数据库中插入一些不同的数据
INSERT INTO [dbo].[Users] ([Username], [Email], [Mobile], [Status])
VALUES 
    ('admin', 'admin@example.com', '13800138000', 0),  -- 状态不同，将被更新
    ('user1', 'user1@other.com', '13900139001', 1),    -- 邮箱和手机不同，将被更新
    ('user3', 'user3@example.com', '13800138003', 1);  -- 在源库不存在，将被删除
</pre>
        </div>

        <h2>2. 创建存储过程</h2>
        <p>以下是一个完整的存储过程示例，用于同步两个数据库中的表数据：</p>
        
        <div class="code-block">
<pre>
CREATE PROCEDURE [dbo].[SyncTableData]
    @SourceDB NVARCHAR(100),      -- 源数据库名
    @TargetDB NVARCHAR(100),      -- 目标数据库名
    @TableName NVARCHAR(100),     -- 要同步的表名
    @KeyColumn NVARCHAR(100),     -- 主键列名
    @Debug BIT = 0                -- 是否调试模式
AS
BEGIN
    SET NOCOUNT ON;
    
    DECLARE @SQL NVARCHAR(MAX);
    DECLARE @Msg NVARCHAR(MAX);
    
    BEGIN TRY
        -- 1. 检查表是否存在
        IF NOT EXISTS (
            SELECT 1 
            FROM [$(SourceDB)].INFORMATION_SCHEMA.TABLES 
            WHERE TABLE_NAME = @TableName
        )
        BEGIN
            RAISERROR('源表不存在', 16, 1);
            RETURN;
        END
        
        -- 2. 获取表结构
        DECLARE @Columns NVARCHAR(MAX);
        SELECT @Columns = STRING_AGG(COLUMN_NAME, ',')
        FROM [$(SourceDB)].INFORMATION_SCHEMA.COLUMNS
        WHERE TABLE_NAME = @TableName;
        
        -- 3. 构建同步SQL
        SET @SQL = '
        MERGE [' + @TargetDB + '].[dbo].[' + @TableName + '] AS Target
        USING [' + @SourceDB + '].[dbo].[' + @TableName + '] AS Source
        ON (Target.[' + @KeyColumn + '] = Source.[' + @KeyColumn + '])
        
        -- 更新匹配的记录
        WHEN MATCHED AND EXISTS (
            SELECT Source.* EXCEPT SELECT Target.*
        )
        THEN UPDATE SET
            ' + REPLACE(@Columns, ',', ' = Source.',) + '
            
        -- 插入新记录
        WHEN NOT MATCHED BY TARGET
        THEN INSERT (' + @Columns + ')
        VALUES (Source.' + REPLACE(@Columns, ',', ',Source.') + ')
        
        -- 删除目标表中多余的记录
        WHEN NOT MATCHED BY SOURCE
        THEN DELETE;';
        
        -- 4. 执行或打印SQL
        IF @Debug = 1
            PRINT @SQL;
        ELSE
            EXEC sp_executesql @SQL;
            
        -- 5. 记录同步信息
        SET @Msg = '表 [' + @TableName + '] 同步完成';
        RAISERROR(@Msg, 10, 1) WITH NOWAIT;
        
    END TRY
    BEGIN CATCH
        SET @Msg = ERROR_MESSAGE();
        RAISERROR(@Msg, 16, 1);
    END CATCH
END
</pre>
        </div>

        <h2>3. 使用示例</h2>
        <p>以下是如何使用这个存储过程的示例：</p>

        <div class="code-block">
<pre>
-- 1. 执行同步（使用上面创建的Users表）
EXEC [dbo].[SyncTableData]
    @SourceDB = 'SourceDB',
    @TargetDB = 'TargetDB',
    @TableName = 'Users',
    @KeyColumn = 'UserID',
    @Debug = 0;

-- 2. 验证同步结果
SELECT 
    s.UserID, s.Username, s.Email, s.Mobile, s.Status,
    t.UserID, t.Username, t.Email, t.Mobile, t.Status
FROM [SourceDB].[dbo].[Users] s
FULL OUTER JOIN [TargetDB].[dbo].[Users] t 
ON s.UserID = t.UserID;

-- 3. 调试模式（只打印SQL不执行）
EXEC [dbo].[SyncTableData]
    @SourceDB = 'SourceDB',
    @TargetDB = 'TargetDB',
    @TableName = 'Users',
    @KeyColumn = 'UserID',
    @Debug = 1;
</pre>
        </div>

        <h2>4. 同步结果说明</h2>
        <p>执行同步后，目标数据库中的数据将发生以下变化：</p>
        <ul>
            <li>admin 用户的 Status 将从 0 更新为 1</li>
            <li>user1 用户的 Email 和 Mobile 将更新为源库的值</li>
            <li>user2 用户将被新增到目标库</li>
            <li>user3 用户将从目标库中删除</li>
        </ul>

        <h2>5. 存储过程说明</h2>
        <table>
            <tr>
                <th>参数</th>
                <th>说明</th>
            </tr>
            <tr>
                <td>@SourceDB</td>
                <td>源数据库名称</td>
            </tr>
            <tr>
                <td>@TargetDB</td>
                <td>目标数据库名称</td>
            </tr>
            <tr>
                <td>@TableName</td>
                <td>要同步的表名</td>
            </tr>
            <tr>
                <td>@KeyColumn</td>
                <td>用于匹配记录的主键列名</td>
            </tr>
            <tr>
                <td>@Debug</td>
                <td>是否为调试模式（1=只打印SQL，0=执行SQL）</td>
            </tr>
        </table>

        <h2>6. 功能特点</h2>
        <ul>
            <li>支持完整的增删改操作</li>
            <li>自动处理表结构</li>
            <li>支持调试模式</li>
            <li>包含错误处理</li>
            <li>使用 MERGE 语句保证原子性</li>
        </ul>

        <div class="warning">
            <strong>注意事项：</strong>
            <ul>
                <li>确保两个数据库中的表结构完全相同</li>
                <li>确保有足够的权限访问两个数据库</li>
                <li>大数据量同步时建议分批处理</li>
                <li>建议先使用调试模式（@Debug=1）查看生成的SQL</li>
            </ul>
        </div>

        <h2>7. 实际应用场景</h2>
        <ul>
            <li>测试环境与生产环境数据同步</li>
            <li>数据库迁移</li>
            <li>数据备份</li>
            <li>分布式系统数据同步</li>
        </ul>
    </div>
</body>
</html> 